<template>
  <view class="page">
    <!-- 顶部导航 -->
    <view class="top-nav">
      <image
          class="back-icon"
          src="/static/icons/pageReturn.svg"
          @click="goBack"
      ></image>
      <text class="title">草本智库</text>
    </view>

    <!-- 聊天内容区 -->
    <scroll-view class="chat-container" :scroll-y="true" :scroll-top="scrollTop" ref="scrollViewRef">
      <view class="message-list">
        <view
            class="message"
            :class="{ 'user-message': msg.role === 'user', 'ai-message': msg.role === 'assistant' }"
            v-for="(msg, index) in messages"
            :key="index"
        >
          <template v-if="msg.role === 'user'">
            <view class="message-content">
              <text class="question-content">{{ msg.content }}</text>
              <!-- 用户发送的图片 -->
              <image
                  v-if="msg.image"
                  :src="msg.image"
                  class="user-image"
                  mode="widthFix"
              ></image>
            </view>
            <view class="avatar user-avatar">U</view>
          </template>

          <template v-if="msg.role === 'assistant'">
            <image class="avatar ai-avatar" src="/static/icons/agent.png"></image>
            <view class="message-content">
              <text class="answer-content">{{ msg.content }}</text>
              <!-- AI回复的图片 -->
              <image
                  v-if="msg.image"
                  :src="msg.image"
                  class="plant-image"
                  mode="widthFix"
              ></image>
            </view>
          </template>

        </view>

        <!-- 加载中指示器 -->
        <view class="loading-indicator" v-if="isStreaming">
          <view class="dot"></view>
          <view class="dot"></view>
          <view class="dot"></view>
        </view>
      </view>
    </scroll-view>

    <!-- 输入框区域 -->
    <view class="input-area">
        <textarea
            class="input-field"
            placeholder="请输入你的指令"
            v-model="userInput"
            @input="adjustTextareaHeight"
            ref="textareaRef"
        ></textarea>
        <!--图片上传和麦克风的垂直容器 -->
        <view class="media-actions">
          <image
              class="upload-icon"
              src="/static/icons/upload.svg"
              @click="chooseImage"
          ></image>
          <VoiceInput
              class="voice-input"
              @transcript="handleVoiceTranscript"
          />
        </view>
        <image
            class="send-icon"
            src="/static/icons/send.svg"
            @click="sendMessage"
            :class="{ disabled: isStreaming || (!userInput.trim() && !selectedImage) }"
        ></image>
        <!-- 上传的图片预览 -->
        <view v-if="selectedImage" class="image-preview">
          <image :src="selectedImage" class="preview-image"></image>
          <text class="remove-image" @click="removeImage">×</text>
        </view>
      </view>
  </view>
</template>

<script setup>
import {getCurrentInstance, nextTick, onMounted, onUnmounted, ref} from 'vue';
import http from '@/http/index.ts';
import {PlantConverter} from '@/utils/PlantConverter';
import agentApi from "@/http/models/agent.ts";
import VoiceInput from '@/components/VoiceInput.vue';

// 组件实例
const instance = getCurrentInstance();
const scrollViewRef = ref(null);

// 元素引用
const textareaRef = ref(null);

// 响应式数据
const scrollTop = ref(0);
const userInput = ref('');
const messages = ref([
  { role: 'assistant', content: '您好！我是草本智库的智能小助手，有什么关于中草药的问题可以问我哦~' }
]);
const isStreaming = ref(false);
const currentChatId = ref('chat_' + Date.now());
const selectedImage = ref(''); // 选中的图片路径
let webSocket = null; // WebSocket实例
let isConnected = false; // 连接状态标记

// 处理语音输入的文字
const handleVoiceTranscript = (transcript) => {
  userInput.value = transcript;
  adjustTextareaHeight();
};

// 返回上一页
const goBack = () => {
  uni.switchTab({
    url: '/pages/study/study'
  })
};

// 调整输入框高度
const adjustTextareaHeight = () => {
  nextTick(() => {
    if (textareaRef.value) {
      textareaRef.value.style.height = 'auto';
      const maxHeight = 120;
      const scrollHeight = textareaRef.value.scrollHeight;
      textareaRef.value.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
    }
  });
};

// 滚动到底部
const scrollToBottom = async () => {
  await nextTick();
  // 使用uni.createSelectorQuery()方法获取元素高度
  const query = uni.createSelectorQuery().in(instance);
  query.select('.message-list').boundingClientRect(res => {
    if (res) {
      scrollTop.value = res.height;
    }
  }).exec();
};

// 解析AI回复中的图片信息
const parseImageFromMessage = (content) => {
  // 匹配"以下是药材xx的图片"格式
  const imageRegex = /以下是药材(.+?)的图片/;
  const match = content.match(imageRegex);

  if (match && match[1]) {
    const plantName = match[1];
    // 尝试获取植物编号
    const plantId = PlantConverter.getIdByName(plantName);

    if (plantId) {
      // 返回图片路径
      console.log(`图片路径：/static/plant/${plantId}.jpg`);
      return `/static/plant/${plantId}.jpg`;
    }
  }

  return null;
};

// 分割消息内容，在图片标识处插入图片
const splitContent = (content, imageSrc) => {
  if (!content) return [];

  // 匹配"以下是药材xx的图片"格式
  const imageRegex = /以下是药材(.+?)的图片/g;
  const matches = content.matchAll(imageRegex);

  const segments = [];
  let lastIndex = 0;

  for (const match of matches) {
    // 添加匹配前的文本
    if (match.index > lastIndex) {
      segments.push({ type: 'text', content: content.substring(lastIndex, match.index) });
    }

    // 添加图片标识文本和图片
    segments.push({ type: 'text', content: match[0] });
    if (imageSrc) {
      segments.push({ type: 'image', content: '' });
    }

    lastIndex = match.index + match[0].length;
  }

  // 添加剩余的文本
  if (lastIndex < content.length) {
    segments.push({ type: 'text', content: content.substring(lastIndex) });
  }

  return segments;
};

// 选择图片
const chooseImage = async () => {
  if (isStreaming.value) return;

  try {
    const res = await uni.chooseImage({
      count: 1, // 只允许选择1张图片
      sizeType: ['original', 'compressed'], // 支持原图和压缩图
      sourceType: ['album', 'camera'] // 支持相册和相机
    });

    // 获取临时图片路径
    selectedImage.value = res.tempFilePaths[0];

    // 调整输入框高度
    adjustTextareaHeight();
  } catch (err) {
    console.error('选择图片失败:', err);
    // 排除用户主动取消的情况
    if (err.errMsg !== 'chooseImage:fail cancel') {
      uni.showToast({
        title: '选择图片失败',
        icon: 'none'
      });
    }
  }
};

// 移除图片
const removeImage = () => {
  selectedImage.value = '';
  adjustTextareaHeight();
};

// 安全地关闭WebSocket连接
const closeWebSocket = () => {
  if (webSocket && isConnected) {
    try {
      webSocket.close();
    } catch (e) {
      console.warn('关闭WebSocket时出错:', e);
    }
  }
  webSocket = null;
  isConnected = false;
};

// 发送消息（支持文字和图片）
const sendMessage = async () => {
  const content = userInput.value.trim();
  // 检查是否有内容或图片
  if (isStreaming.value || (!content && !selectedImage.value)) return;

  // 添加用户消息
  const userMsg = {
    role: 'user',
    content
  };

  // 如果有图片，处理图片
  if (selectedImage.value) {
    // 先显示本地图片
    userMsg.image = selectedImage.value;
  }

  messages.value.push(userMsg);
  userInput.value = '';
  selectedImage.value = '';
  if (textareaRef.value) textareaRef.value.style.height = 'auto';
  await scrollToBottom();

  // 添加AI回复占位
  messages.value.push({ role: 'assistant', content: '' });
  isStreaming.value = true;

  try {
    // 安全地关闭之前的WebSocket连接（如果存在）
    closeWebSocket();

    // 如果有图片，则先通过HTTP上传图片
    let fileName = null;
    if (userMsg.image) {
      try {
        const uploadResult = await agentApi.uploadFile(userMsg.image);
        if (uploadResult.code === 200) {
          fileName = uploadResult.data.fileName;
          console.log('文件上传成功，文件名:', fileName);
        }
      } catch (uploadError) {
        uni.showToast({
          title: uploadError,
          icon: 'none'
        })
      }
    }


    // 构建WebSocket URL（注意：http对应ws，https对应wss）
    const baseWsUrl = http.baseURL.replace('http://', 'ws://').replace('https://', 'wss://');
    // 在URL中包含文本内容和文件名
    let wsUrl = `${baseWsUrl}/agent/service/ws?prompt=${encodeURIComponent(content)}&chatId=${currentChatId.value}`;
    if (fileName) {
      wsUrl += `&fileName=${encodeURIComponent(fileName)}`;
    }
    console.log('WebSocket连接地址:', wsUrl);

    // 建立WebSocket连接（此时文本和文件引用一起发送）
    webSocket = uni.connectSocket({
      url: wsUrl,
      method: 'GET',
      success: () => console.log('WebSocket连接中...'),
      fail: (err) => console.error('WebSocket连接失败:', err)
    });

    // 监听WebSocket打开
    webSocket.onOpen(() => {
      console.log('WebSocket已连接');
      isConnected = true;
    });

    // 监听WebSocket消息（核心：接收流式数据）
    webSocket.onMessage((res) => {
      // 接收后端发送的分块数据（res.data为字符串）
      const chunk = res.data;
      console.log('收到WebSocket数据:', chunk);

      // 更新AI回复内容
      const lastMessageIndex = messages.value.length - 1;
      messages.value[lastMessageIndex].content += chunk;

      // 检查是否有图片信息
      const imagePath = parseImageFromMessage(messages.value[lastMessageIndex].content);
      if (imagePath) {
        messages.value[lastMessageIndex].image = imagePath;
      }

      scrollToBottom();
    });

    // 监听WebSocket关闭
    webSocket.onClose((res) => {
      console.log('WebSocket已关闭:', res);
      isConnected = false;
      isStreaming.value = false;
      scrollToBottom();
    });

    // 监听WebSocket错误
    webSocket.onError((err) => {
      console.error('WebSocket错误:', err);
      isConnected = false;
      isStreaming.value = false;
      throw new Error(`WebSocket错误: ${err.errMsg || '连接失败'}`);
    });

  } catch (error) {
    console.error('发送消息异常:', error);
    // 更新错误信息
    messages.value[messages.value.length - 1].content = `请求失败：${error.message || '未知错误'}`;
    isStreaming.value = false;
  }
};

// 页面卸载时关闭WebSocket
onUnmounted(() => {
  closeWebSocket();
});

onMounted(async () => {
  await scrollToBottom();
});
</script>

<style scoped lang="scss">
@import '../../styles/ai-qa.scss';
</style>